package cn.org.xiaoweiba.graduationdesign.bookmall.utils;

import java.util.Random;

/**
 * 和随机 random 相关的工具类
 */
public class RandomUtil {

    /**
     * 十进制数字字符组成的数组
     */
    private final static char[] decimalNumChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

    /**
     * 小写英文字符组成的数组
     */
    private final static char[] lowerEnglishChars = {
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
            'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
            'y', 'z'
    };

    /**
     * 十进制数字字符、大写英文字符、小写英文字符组成的数组
     */
    private final static char[] decimalLowerUpperChars = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
            'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
            'u', 'v', 'w', 'x', 'y', 'z',
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
            'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
            'U', 'V', 'W', 'X', 'Y', 'Z'
    };

    private RandomUtil() {
    }

    /**
     * 生成 0(包含) - bound(不包含) 之间的随机 int 整数
     *
     * @param bound 生成的随机 int 整数的上限(不包含)
     * @return 0(包含) - bound(不包含) 之间的随机 int 整数
     */
    public static int generateRandomIntBetweenZeroAndBoundExcluded(int bound) {
        return new Random().nextInt(bound);
    }

    /**
     * 生成 0(包含) - bound(包含) 之间的随机 int 整数
     *
     * @param bound 生成的随机 int 整数的上限(包含)
     * @return 0(包含) - bound(包含) 之间的随机 int 整数
     */
    public static int generateRandomIntBetweenZeroAndBound(int bound) {
        return generateRandomIntBetweenZeroAndBoundExcluded(bound + 1);
    }

    /**
     * 生成指定范围 [origin(包含) - bound(不包含)] 之间的随机 int 整数
     *
     * @param origin 生成的随机 int 整数的下限(包含)
     * @param bound  生成的随机 int 整数的上限(不包含)
     * @return [origin(包含) - bound(不包含)] 之间的随机 int 整数
     */
    public static int generateRandomIntBetweenOriginAndBoundExcluded(int origin, int bound) {
        return new Random().nextInt(origin, bound);
    }

    /**
     * 生成指定范围 [origin(包含) - bound(包含)] 之间的随机 int 整数
     *
     * @param origin 生成的随机 int 整数的下限(包含)
     * @param bound  生成的随机 int 整数的上限(包含)
     * @return [origin(包含) - bound(包含)] 之间的随机 int 整数
     */
    public static int generateRandomIntBetweenOriginAndBound(int origin, int bound) {
        return generateRandomIntBetweenOriginAndBoundExcluded(origin, bound + 1);
    }

    /**
     * 根据给定的字符数组和随机字符串的指定长度，生成指定长度的随机字符串
     *
     * @param chars        生成指定长度的随机字符串中每个字符的来源
     * @param randomStrLen 随机字符串的指定长度
     * @return 指定长度的随机字符串
     */
    public static String generateRandomStrByChars(char[] chars, int randomStrLen) throws RuntimeException {
        // 给定的字符数组为空时，抛出运行时异常
        if (chars == null || chars.length == 0) {
            throw new RuntimeException("参数 {chars} 应当不为空 (不为 null，且数组长度大于 0)");
        }
        // 指定的要生成的随机字符串长度小于等于 0 抛出运行时异常
        if (randomStrLen <= 0) {
            throw new RuntimeException("参数 {randomStrLen} 的取值应当大于 0");
        }
        // 随机字符串生成过程中的字符串
        StringBuilder randomStr = new StringBuilder();
        // 生成指定长度的随机字符串
        for (int i = 0; i < randomStrLen; i++) {
            // 每次从给定的字符数组中随机取出一个字符
            randomStr.append(chars[generateRandomIntBetweenZeroAndBoundExcluded(chars.length)]);
        }
        return randomStr.toString();
    }

    /**
     * 生成指定长度的随机数字符串
     *
     * @param randomNumStrLen 随机数字符串的长度
     * @return 指定长度的随机数字符串
     */
    public static String generateRandomNumStr(int randomNumStrLen) throws RuntimeException {
        // 指定的要生成的随机数字符串长度小于等于 0 抛出运行时异常
        if (randomNumStrLen <= 0) {
            throw new RuntimeException("参数 {randomNumStrLen} 的取值应当大于 0");
        }
        // 生成指定长度的随机数字符串
        return generateRandomStrByChars(decimalNumChars, randomNumStrLen);
    }

    /**
     * 生成指定长度的小写英文字符串
     *
     * @param randomLowerEnglishStrLen 小写英文字符串的长度
     * @return 指定长度的小写英文字符串
     */
    public static String generateRandomLowerEnglishStr(int randomLowerEnglishStrLen) throws RuntimeException {
        // 指定的要生成的字符串长度小于等于 0 抛出运行时异常
        if (randomLowerEnglishStrLen <= 0) {
            throw new RuntimeException("参数 {randomLowerEnglishStrLen} 的取值应当大于 0");
        }
        // 生成指定长度的小写英文字符串
        return generateRandomStrByChars(lowerEnglishChars, randomLowerEnglishStrLen);
    }

    /**
     * 生成指定长度的大写英文字符串
     *
     * @param randomUpperEnglishStrLen 大写英文字符串的长度
     * @return 指定长度的大写英文字符串
     */
    public static String generateRandomUpperEnglishStr(int randomUpperEnglishStrLen) throws RuntimeException {
        // 指定的要生成的字符串长度小于等于 0 抛出运行时异常
        if (randomUpperEnglishStrLen <= 0) {
            throw new RuntimeException("参数 {randomUpperEnglishStrLen} 的取值应当大于 0");
        }
        // 生成指定长度的大写英文字符串
        return generateRandomLowerEnglishStr(randomUpperEnglishStrLen).toUpperCase();
    }

    /**
     * 生成指定长度的由十进制数字、大写、小写英文字符组成的随机字符串
     *
     * @param randomNumLowerUpperStrLen 随机字符串的长度
     * @return 指定长度的由十进制数字、大写、小写英文字符组成的随机字符串
     */
    public static String generateRandomNumLowerUpperStr(int randomNumLowerUpperStrLen) throws RuntimeException {
        // 指定的要生成的字符串长度小于等于 0 抛出运行时异常
        if (randomNumLowerUpperStrLen <= 0) {
            throw new RuntimeException("参数 {randomNumLowerUpperStrLen} 的取值应当大于 0");
        }
        // 生成指定长度的由十进制数字、大写、小写英文字符组成的随机字符串
        return generateRandomStrByChars(decimalLowerUpperChars, randomNumLowerUpperStrLen);
    }

    /**
     * 生成指定长度的由十进制数字、大写英文字符组成的随机字符串
     *
     * @param randomNumUpperStrLen 随机字符串的长度
     * @return 指定长度的由十进制数字、大写英文字符组成的随机字符串
     */
    public static String generateRandomNumUpperStr(int randomNumUpperStrLen) throws RuntimeException {
        // 指定的要生成的字符串长度小于等于 0 抛出运行时异常
        if (randomNumUpperStrLen <= 0) {
            throw new RuntimeException("参数 {randomNumUpperStrLen} 的取值应当大于 0");
        }
        // 生成指定长度的由十进制数字、大写英文字符组成的随机字符串
        return generateRandomNumLowerUpperStr(randomNumUpperStrLen).toUpperCase();
    }

    /**
     * 生成指定长度的由十进制数字、小写英文字符组成的随机字符串
     *
     * @param randomNumLowerStrLen 随机字符串的长度
     * @return 指定长度的由十进制数字、小写英文字符组成的随机字符串
     */
    public static String generateRandomNumLowerStr(int randomNumLowerStrLen) throws RuntimeException {
        // 指定的要生成的字符串长度小于等于 0 抛出运行时异常
        if (randomNumLowerStrLen <= 0) {
            throw new RuntimeException("参数 {randomNumLowerStrLen} 的取值应当大于 0");
        }
        // 生成指定长度的由十进制数字、小写英文字符组成的随机字符串
        return generateRandomNumLowerUpperStr(randomNumLowerStrLen).toLowerCase();
    }

}
